using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class PlayerManager : MonoBehaviour
{
    public delegate void LevelFinishedEventHandler(object sender, LevelFinishedEventArgs e);
    public delegate void PassedCheckpointEventHandler(object sender, PassedCheckpointEventArgs e);
    public delegate void PlayerResetEventHandler(object sender, PlayerResetEventArgs e);

    private int score;
    private double time;
    private int waitForReset;
    private bool reset;

    public static event LevelFinishedEventHandler OnLevelFinished;
    public static event PassedCheckpointEventHandler OnPassedCheckpoint;
    public static event PlayerResetEventHandler OnPlayerReset;

    public Savegame savegame;

    private void Start()
    {
        EventManager.OnCollision += EventManagerOnCollision;
        EventManager.OnPlayerDied += EventManagerOnPlayerDied;

        waitForReset = 0;
        AllCheckpoints.InitializeCheckpoints();

        savegame = new Savegame(0, AllLevels.GetLevelIdByName(Application.loadedLevelName), time, score);
    }

    void EventManagerOnPlayerDied(object sender)
    {
        SetPlayerToLastCheckpoint();
    }

    private void Update()
    {
        this.time += Time.deltaTime;

        if (reset)
        {
            waitForReset--;
            if (waitForReset == 0)
                reset = false;
        }

        Player.Powerup.Update();
    }

    private void EventManagerOnCollision(object sender, CollisionEventArgs e)
    {
        switch (e.OtherObject.tag)
        {
            case "Enemy":
                break;
            case "Checkpoint":
                if (e.CollisionType == CollisionType.Enter)
                {
                    if (AllCheckpoints.AddCheckpointToPassedCheckpoints(time, score, e.OtherObject.name))
                    {
                        savegame = new Savegame(AllCheckpoints.PassedCheckpoints.Count - 1, AllLevels.GetLevelIdByName(Application.loadedLevelName), time, score);
                        if (OnPassedCheckpoint != null)
                            OnPassedCheckpoint(this,
                                               new PassedCheckpointEventArgs
                                                   {
                                                       PassedCheckpoint = AllCheckpoints.PassedCheckpoints.Last()
                                                   });
                    }
                }
                break;
            case "Powerup":
                Player.Powerup.SetType(e.OtherObject.name);
                break;
            case "Finish":
                if (OnLevelFinished != null)
                {
                    OnLevelFinished(this,
                                    new LevelFinishedEventArgs
                                        {
                                            Level = Application.loadedLevelName.Replace("Level", ""),
                                            Time = this.time,
                                            Score = this.score
                                        });

                    //TODO: OnLevelFinished aktionen
                    EventManager.NextLevel = "Map";
                }
                break;
            case "Kill":
                if (e.CollisionType == CollisionType.Enter && !reset && waitForReset == 0)
                {
                    reset = true;
                    waitForReset = 2;
                    AddPlayerHealth(-Player.HitPoints);
                }
                break;
        }
    }

    private void SetPlayerToLastCheckpoint()
    {
        Checkpoint last = AllCheckpoints.GetLastCheckpoint();
        if (OnPlayerReset == null) return;
        OnPlayerReset(this, new PlayerResetEventArgs(last));
        this.time = last.Time;
        this.score = last.Score;
    }

    private void AddPlayerHealth(int amount)
    {
        Player.AddHitPoints(amount, this);
    }

    private void UpdateScore()
    {
        this.score += 1;
    }

    private void OnDestroy()
    {
        EventManager.OnCollision -= EventManagerOnCollision;
    }
}

public class PlayerResetEventArgs : EventArgs
{
    public PlayerResetEventArgs(Checkpoint resetCheckpoint)
    {
        reset = resetCheckpoint;
    }

    public Checkpoint reset;
}